#include "clienttcp.h"
#include <QDebug>
const QString ClientTcp::SERVER_ADDRESS = "127.0.0.1";
const quint16 ClientTcp::SERVER_PORT = 12345;
const int ClientTcp::CONNECT_TIMEOUT_MS = 3000;
const int ClientTcp::RESPONSE_TIMEOUT_MS = 5000;
ClientTcp::ClientTcp(QObject *parent)
    : QObject(parent),
      m_workerThread(new QThread(this)),
      m_socket(nullptr),
      m_connectTimer(nullptr),
      m_responseTimer(nullptr)
{
    this->moveToThread(m_workerThread);
    m_workerThread->start();
}
ClientTcp::~ClientTcp()
{
    m_workerThread->requestInterruption();
        m_workerThread->quit();
        if (!m_workerThread->wait(2000)) {
            m_workerThread->terminate(); // 强制终止
        }
        delete m_workerThread;
}
void ClientTcp::startLogin(const QString &user, const QString &pass)
{
    QMetaObject::invokeMethod(this, [this, user, pass]{
        handleLogin(user, pass);
    }, Qt::QueuedConnection);
}
void ClientTcp::handleLogin(const QString &user, const QString &pass)
{
    QMutexLocker locker(&m_mutex);
    cleanupResources();
    m_socket = new QTcpSocket();
    m_readBuffer.clear();
    // 连接超时定时器
    m_connectTimer = new QTimer();
    m_connectTimer->setSingleShot(true);
    QObject::connect(m_connectTimer, &QTimer::timeout, this, [this]{
        QMutexLocker locker(&m_mutex);
        if(m_socket && m_socket->state() == QAbstractSocket::ConnectingState) {
            handleError("Connection timeout");
        }
    });
    // 响应超时定时器
    m_responseTimer = new QTimer();
    m_responseTimer->setSingleShot(true);
    QObject::connect(m_responseTimer, &QTimer::timeout, this, [this]{
        QMutexLocker locker(&m_mutex);
        if(m_socket && m_socket->state() == QAbstractSocket::ConnectedState) {
            handleError("Response timeout");
        }
    });
    // 连接信号
    QObject::connect(m_socket, &QTcpSocket::connected, this, [=]{
        QMutexLocker locker(&m_mutex);
        m_connectTimer->stop();

        const QString data = QString("login,%1,%2\n").arg(user).arg(pass);
        if(m_socket->write(data.toUtf8()) == -1) {
            handleError("Write failed: " + m_socket->errorString());
            return;
        }
        m_responseTimer->start(RESPONSE_TIMEOUT_MS);
    });
    QObject::connect(m_socket, &QTcpSocket::readyRead, this, &ClientTcp::onReadyRead);
    QObject::connect(m_socket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error),
                    this, &ClientTcp::onError);
    m_connectTimer->start(CONNECT_TIMEOUT_MS);
    m_socket->connectToHost(SERVER_ADDRESS, SERVER_PORT);
}
void ClientTcp::onReadyRead()
{
    QMutexLocker locker(&m_mutex);
    if(!m_socket) return;
    m_readBuffer += m_socket->readAll();

    int pos;
    while((pos = m_readBuffer.indexOf('\n')) != -1) {
        const QByteArray packet = m_readBuffer.left(pos).trimmed();
        m_readBuffer = m_readBuffer.mid(pos + 1);

        if(packet.isEmpty()) continue;
        if(m_responseTimer && m_responseTimer->isActive()) {
            m_responseTimer->stop();
        }
        bool success = packet.startsWith("login true");
        QMetaObject::invokeMethod(this, [this, success]{
            emit loginResult(success);
        }, Qt::QueuedConnection);

        if(m_socket->state() == QAbstractSocket::ConnectedState) {
            m_socket->disconnectFromHost();
        }
    }
}
void ClientTcp::onError(QAbstractSocket::SocketError socketError)
{
    Q_UNUSED(socketError);
    QMutexLocker locker(&m_mutex);
    if(!m_socket) return;

    handleError(m_socket->errorString());
}
void ClientTcp::cleanupResources()
{
    if(m_connectTimer) {
        m_connectTimer->stop();
        m_connectTimer->deleteLater();
        m_connectTimer = nullptr;
    }
    if(m_responseTimer) {
        m_responseTimer->stop();
        m_responseTimer->deleteLater();
        m_responseTimer = nullptr;
    }
    if(m_socket) {
        m_socket->disconnect();
        m_socket->abort();
        m_socket->deleteLater();
        m_socket = nullptr;
    }
}
void ClientTcp::handleError(const QString &msg)
{
    qWarning() << "Error occurred:" << msg;
    cleanupResources();
    QMetaObject::invokeMethod(this, [this]{ emit loginResult(false); }, Qt::QueuedConnection);
}
